/**
 * 缓冲区对象
 *  问题：assignVertexAttrib3f等方法一次只能绘制一个点，
 *    对那些由多个顶点组成的图形，比如三角形、矩形和立方体，
 *    需要一次性地将图形的顶点全部传入顶点着色器，然后才能把
 *    图形画出来
 *  描述：
 *    缓冲区对象是一块内存区域，可以一次性地向着色器传入多个顶点的数据
 *  解决：需要一次性地将图形的顶点全部传入顶点着色器，才能把图形画出来
 *    可以一次性地向缓冲区对象中填充大量的顶点数据，然后将这些数据保存在其中，
 *    供顶点着色器使用
 *  是webgl系统中的一块存储区
 * 
 * 使用缓冲区对象向顶点着色器传入多个顶点的数据，需要遵循的五个步骤
 *  创建缓冲区对象 => 绑定缓冲区对象 => 将数据写入缓冲区对象
 *  => 将缓冲区对象分配给一个attribute变量 => 开启attribute变量
 * 
 */
 import { baseError } from "../../debug";
 // 初始化buffer
 /**
  * 
  * @param gl 
  * @param loc 
  * @param data 
  * @param dataSize 每个变量需要的数据
  * @param stride 指定相邻两个顶点间的字节数
  * @param offset 指定缓冲区对象中的偏移量(以字节为单位)，即attribte变量从缓冲区中的何处开始存储。
  */
 export function initVertexBuffer(gl, loc, data, dataSize, stride = 0, offset = 0) {
   // 第一步
   let vertexBuffer = createBuffer(gl)
   // 第二步
   bindBuffer(gl, vertexBuffer)
   // 第三步
   writeBuffer(gl, data)
   // 第四步：将缓冲区数据读取到 GPU
   assignBuffer(gl, loc, dataSize, stride, offset)
   // 第五步
   enableBuffer(gl, loc)
 }
 /**
  * 将顶点和 index 下标数据都输入到缓冲区
  * @param gl 
  * @param loc 
  * @param data 
  * @param indexArr data的下标数据
  * @param dataSize 每个变量需要的数据
  * @param stride 指定相邻两个顶点间的字节数
  * @param offset 指定缓冲区对象中的偏移量(以字节为单位)，即attribte变量从缓冲区中的何处开始存储。
  */
 export function initVertexIndexBuffer(gl, loc, data, indexArr, dataSize, stride = 0, offset = 0) {
   // 第一步
   const vertexBuffer = createBuffer(gl)
   if (!vertexBuffer) {
     console.log('Failed to create the buffer object');
     return -1;
   }
   // 第二步
   bindBuffer(gl, vertexBuffer)
   // 第三步
   writeBuffer(gl, data)
   // 第四步：将缓冲区数据读取到 GPU
   assignBuffer(gl, loc, dataSize, stride, offset)
   // 第五步
   enableBuffer(gl, loc)
   // 第六步
   const indexBuffer = createBuffer(gl)
   // 第七步
   bindIndexBuffer(gl, indexBuffer)
   // 第八步
   writeIndexBuffer(gl, indexArr)
 }
 
 // 第一步：创建缓冲区对象
 function createBuffer(gl) {
   let buffer = gl.createBuffer();
   if (!buffer) {
     baseError('Failed to create the buffer object');
     return -1;
   }
   return buffer
 }
 
 /**
  * 第二步：绑定缓冲区对象：将缓冲区对象绑定到webgl系统中已经存在的目标上
  * @param1
  *  gl.ARRAY_BUFFER             表示缓冲区对象中包含了顶点的数据
  *  gl.ELEMENT_ARRAY_BUFFER     表示缓冲区对象中包含了顶点的索引值
  * @param2                      指定之前由gl.createBuffer()返回的待绑定的缓冲区对象
  */
 function bindBuffer(gl, buffer) {
   gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
 }
 
 function bindIndexBuffer(gl, buffer) {
   gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);
 }
 /**
  * 第三步：将数据写入缓冲区对象
  * 开辟存储空间，向绑定在target上的缓冲区对象中写入数据data
  * @param1
  *  gl.ARRAY_BUFFER或gl.ELEMENT_ARRAY_BUFFER
  * @param2
  *  写入缓冲区对象的数据(类型化数组)
  * @param3
  *  表示程序将如何使用存储在缓冲区对象中的数据。该参数将帮助webgl优化操作，
  *  但是就算你传入了错误的值，也不会终止程序(仅仅是降低程序的效率)
  *  gl.STATIC_DRAW    只会向缓冲区对象中写入一次数据，但需要绘制很多次
  *  gl.STREAM_DRAW    只会向缓冲区对象中写入一次数据，然后绘制若干次
  *  gl.DYNAMIC_DRAW   会向缓冲区对象中多次写入数据，并绘制很多次
  */
 function writeBuffer(gl, data) {
   gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
 }
 function writeIndexBuffer(gl, data) {
   gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data, gl.STATIC_DRAW);
 }
 
 /**
  * 第四步：将缓冲区对象分配给一个attribute变量
  * 将缓冲区对象的引用或指针分配给attribute变量
  * @param1
  *  location            指定待分配attribute变量的存储位置
  * @param2
  *  size                指定缓冲区中每个顶点的分量个数(1到4)。若size比attribute变量需要的分量数小，
  *                      缺失分量将按照与gl.vertexAttrib[1234]f相同的规则补全
  *                      比如，如果size为1，那么第2、3分量自动设为0，第4分量为1
  * @param3
  *  type                用以下类型之一来指定数据格式
  *                      gl.UNSIGNED_BYTE    无符号字节，UInt8Array
  *                      gl.SHORT            短整型，Int16Array
  *                      gl.UNSIGNED_SHORT   无符号短整型，UInt16Array
  *                      gl.INT              整型，Int32Array
  *                      gl.UNSIGNED_INT     无符号整型，UInt32Array
  *                      gl.FLOAT            浮点型，Float32Array
  * @param4
  *  normalize           传入true或false，表明是否将非浮点型的数据归一化到[0,1]或[-1,1]区间
  * @param5
  *  stride              指定相邻两个顶点间的字节数，默认为0(参见第四章)
  * @param6
  *  offset              指定缓冲区对象中的偏移量(以字节为单位)，即attribte变量从缓冲区中的何处开始存储。
  * 
  * @return              
  *  INVALID_OPERATION   不存在当前程序对象
  *  INVALID_VALUE       location大于等于attribute变量的最大数目(默认为8)。或者stride或offset是负值
  */
 
 function assignBuffer(gl, loc, dataSize, stride = 0, offset = 0) {
   gl.vertexAttribPointer(loc, dataSize, gl.FLOAT, false, stride, offset);
 }
 /**
  * 第五步：开启attribute变量
  * 使缓冲区对attribute变量的分配生效
  * @param   location
  */
 function enableBuffer(gl, loc) {
   gl.enableVertexAttribArray(loc);
 }
 // 关闭attribute分配
 export function disableBuffer(gl, loc) {
   gl.disableVertexAttribArray(loc)
 }
 
 // 删除缓冲区对象
 
 export function delBuffer(gl, buffer) {
   gl.deleteBuffer(buffer)
 }
 